import {Ref} from 'vue'

export interface SSEOptions {
  // 数据累加到的响应式变量
  targetRef: Ref<string>
  // 是否在开始前清空目标变量
  clearBeforeStart?: boolean
  // 数据处理函数，可选
  onData?: (data: string) => string
  // 错误处理函数
  onError?: (error: Error) => void
  // 完成处理函数
  onComplete?: () => void
}

export async function fetchStream(url: string, options: RequestInit): Promise<ReadableStreamDefaultReader<Uint8Array>> {
  const response = await fetch(url, options)
  
  if (!response.ok) {
    throw new Error(`Request failed: ${response.statusText}`)
  }
  
  if (!response.body) {
    throw new Error('No response body')
  }
  
  return response.body.getReader()
}

export class SSEClient {
  /**
   * 处理SSE流式响应
   * @param reader - ReadableStreamDefaultReader
   * @param options - SSE处理选项
   */
  static async processStream(
      reader: ReadableStreamDefaultReader<Uint8Array>,
      options: SSEOptions
  ): Promise<void> {
    const {targetRef, clearBeforeStart = false, onData, onError, onComplete} = options

    if (clearBeforeStart) {
      targetRef.value = ''
    }

    const textDecoder = new TextDecoder()
    let buffer = ''

    try {
      let done = false

      while (!done) {
        const {value, done: readerDone} = await reader.read()
        done = readerDone

        if (value) {
          // 解码并添加到缓冲区
          buffer += textDecoder.decode(value, {stream: true})

          // 按双换行符分割事件
          const events = buffer.split('\n\n')
          // 保留最后一个可能不完整的事件
          buffer = events.pop() || ''

          for (const event of events) {
            if (event.trim() === '') continue

            // 每个事件可能包含多行
            const lines = event.split('\n')

            for (const line of lines) {
              if (line.startsWith('data:')) {
                // 注意：不要使用 trim()，保留原始内容包括空格
                const content = line.slice(5)

                if (content === '[DONE]') {
                  // 处理结束标记
                  break
                }

                // 检查是否为空行（data: 后面没有任何内容）
                if (content === '') {
                  // 连续的空 data: 表示段落分隔
                  targetRef.value += '\n'
                } else {
                  try {
                    // 尝试解析 JSON 格式的数据
                    const dataObj = JSON.parse(content)
                    let data = dataObj.text || content

                    // 如果提供了数据处理函数，使用它
                    if (onData) {
                      data = onData(data)
                    }

                    // 累加到目标响应式变量
                    targetRef.value += data
                  } catch (e) {
                    // 如果不是 JSON，直接使用原始内容
                    let data = content
                    if (onData) {
                      data = onData(data)
                    }
                    targetRef.value += data
                  }
                }
              }
              // 忽略其他SSE字段（event:, id:, retry: 等）
            }
          }
        }
      }

      // 处理缓冲区中剩余的数据
      if (buffer.trim()) {
        const lines = buffer.split('\n')
        for (const line of lines) {
          if (line.startsWith('data:')) {
            // 保留原始内容，不要 trim
            const content = line.slice(5)
            if (content !== '[DONE]') {
              if (content === '') {
                targetRef.value += '\n'
              } else if (content === '\n') {
                targetRef.value += '\n'
              } else {
                try {
                  const dataObj = JSON.parse(content)
                  let data = dataObj.text || content
                  if (onData) {
                    data = onData(data)
                  }
                  targetRef.value += data
                } catch (e) {
                  let data = content
                  if (onData) {
                    data = onData(data)
                  }
                  targetRef.value += data
                }
              }
            }
          }
        }
      }
      onComplete?.()
    } catch (error) {
      onError?.(error as Error)
      throw error
    }
  }

  /**
   * 发送SSE请求并处理响应
   * @param url - 请求URL
   * @param requestOptions - fetch请求选项
   * @param sseOptions - SSE处理选项
   */
  static async request(
      url: string,
      requestOptions: RequestInit,
      sseOptions: SSEOptions
  ): Promise<void> {
    try {
      const response = await fetch(url, requestOptions)

      if (!response.ok) {
        throw new Error(`Request failed: ${response.statusText}`)
      }

      if (!response.body) {
        throw new Error('No response body')
      }

      const reader = response.body.getReader()
      await this.processStream(reader, sseOptions)
    } catch (error) {
      sseOptions.onError?.(error as Error)
      throw error
    }
  }
}
